package nc.bs.common.freereport;
import java.lang.reflect.Field;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.ufida.report.anareport.FreeReportContextKey;
import com.ufida.report.anareport.base.BaseQueryCondition;

import nc.bs.bd.util.DBAUtil;
import nc.bs.dao.BaseDAO;
import nc.bs.dao.DAOException;
import nc.jdbc.framework.SQLParameter;
import nc.jdbc.framework.processor.ColumnListProcessor;
import nc.pub.smart.model.code.CodeProcessor;
import nc.pub.smart.model.preferences.Parameter;
import nc.vo.pub.BusinessException;
import nc.vo.pub.SuperVO;
import nc.vo.pub.query.ConditionVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class AbstractProcessor {

    /** 数据加工自定义代码基类 */
    private CodeProcessor processor = null;
    /** 表对象 **/
    private AbstractTmpTableInfo absTable = null;
    /**临时表名*/
    private String tableName = null;
    /**表字段*/
    private String[] columns = null;
    /**表字段类型*/
    private String[] columnTypes = null;
    /**查询条件*/
    private Map<String,Object> conditionMap = null;
    /**数据连接*/
    private BaseDAO dao = null;
    /**组织*/
    private String pk_org = null;
    /**集团*/
    private String pk_group = null;

    private final Logger logger = LoggerFactory.getLogger(AbstractProcessor.class);

    public AbstractProcessor(CodeProcessor processor) {
        this.processor = processor;
    }

    public CodeProcessor getProcessor() {
        return processor;
    }

    public void setProcessor(CodeProcessor processor) {
        this.processor = processor;
    }


    /**
     * 执行过程，查询-整理-插入临时表-返回结果
     * @return
     * @throws BusinessException
     * @throws ParseException
     */
    public String getResultSql() throws BusinessException, ParseException {
        BaseQueryCondition condition = (BaseQueryCondition) processor
                .getContext().getAttribute(
                        FreeReportContextKey.KEY_IQUERYCONDITION);
        initTempTableDatas();
        // 创建临时表
        createTempTable();
        if(null == condition)//点击语义模型时会触发此类，此时condition是null
            return getSQL();
        initQryCondition(condition);
        SuperVO[] vos = queryDatas();
        if(vos != null && vos.length > 0)
            insertDatasTOTable(vos);
        return getSQL();
    }

    String getSQL(){
        return "select " + getSelFieldsByTmpTableColumns(this.columns) + " from " + this.tableName;
    }
    /**
     * 查询数据
     * @return
     * @throws ParseException
     * @throws DAOException
     */
    public abstract SuperVO[] queryDatas() throws BusinessException, ParseException;

    /**
     * 查询结果插入到临时表中
     * @param vos
     * @throws BusinessException
     */
    private void insertDatasTOTable(SuperVO[] vos) throws BusinessException {
        String inPramas = getInsertValueParams(this.columns.length);

        StringBuffer insertSql = new StringBuffer();
        insertSql.append("insert into ");
        insertSql.append(this.tableName);
        insertSql.append("(");
        insertSql.append(getSelFieldsByTmpTableColumns(this.columns));
        insertSql.append(") values (");
        insertSql.append(inPramas);
        insertSql.append(")");

        List<SQLParameter> sqlParams = getSqlParameters(vos);

        DBAUtil.execBatchSql(insertSql.toString(), sqlParams);
    }


    /**
     * 获取插入临时表的parameter
     * @param vos
     * @return
     */
    private List<SQLParameter> getSqlParameters(SuperVO[] vos) {
        Class<? extends SuperVO> clazz = vos[0].getClass();
        List<SQLParameter> lst = new ArrayList();
        for(SuperVO vo : vos){
            SQLParameter param = new SQLParameter();
            for(String column : this.columns){
                try {
                    Field field = clazz.getDeclaredField(column);
                    field.setAccessible(true);
                    Object object = field.get(vo);
                    if(object == null){
                        param.addParam("");
                    }else{
                        param.addParam(object);
                    }
                } catch (NoSuchFieldException | SecurityException e) {
                } catch (IllegalArgumentException e) {
                } catch (IllegalAccessException e) {
                }
            }
            lst.add(param);
        }
        return lst;
    }

    private AbstractTmpTableInfo getTmpTabInfo() {
        if(this.absTable == null)
            this.absTable = getAbsTableInfo();
        return this.absTable;
    }

    public abstract  AbstractTmpTableInfo getAbsTableInfo() ;

    /**
     * 将查询模板中的某些条件取到，方便查询的时候使用
     */
    private void initQryCondition(BaseQueryCondition condition) {
        Parameter[] params = (Parameter[]) condition.getUserContext().get("keyReportParamWeb");
        String currentReportOrg = (String) condition.getUserContext().get("CurrentReportOrg");
        Map<String,Object> map = new HashMap<>();
        map.put("currentReportOrg", currentReportOrg);
        if (params != null) {
            for (Parameter param : params) {
                map.put(param.getCode(), param.getValue());
            }
        }

        // 查询条件
        ConditionVO[] conditions = (ConditionVO[]) condition.getUserContext().get("freereport_querycondition_vos");
        if (conditions != null) {
            for (ConditionVO vo : conditions) {
                map.put(vo.getFieldCode(), vo.getValue());
            }
        }

        this.conditionMap = map;
    }

    /**
     * 初始化数据库临时表信息
     */
    private void initTempTableDatas(){
        AbstractTmpTableInfo tmpTabInfo = getTmpTabInfo();
        this.tableName = tmpTabInfo.getTableName();
        this.columns = tmpTabInfo.getTableColumns();
        this.columnTypes = tmpTabInfo.getTableColumnTypes();
    }

    /**
     * 创建临时表
     * @return
     * @throws BusinessException
     */
    private void createTempTable()
            throws BusinessException {
        try {
            // 临时表 :表名、表字段名、表字段类型
            TempTableDAO.getInstance().createTable(this.tableName,this.columns,this.columnTypes);
        } catch (BusinessException e) {
            logger.error("创建临时表失败" + e.getMessage());
            throw new BusinessException("创建临时表失败");
        }
    }

    /**
     * 通过组织查询出所属集团
     * @return
     * @throws DAOException
     */
    public String getGroupByOrg() throws BusinessException {
        if(this.pk_group == null){
            String sql = "select pk_group from org_orgs where pk_org=?";
            SQLParameter param = new SQLParameter();
            param.addParam(this.pk_org);
            List<String> groupLst = (List<String>) getDao().executeQuery(sql, param, new ColumnListProcessor());
            this.pk_group = groupLst == null ? null : groupLst.get(0);
        }
        return this.pk_group;
    }

    public Map<String, Object> getConditionMap() {
        return conditionMap;
    }

    public BaseDAO getDao() {
        if(dao == null)
            dao = new BaseDAO();
        return dao;
    }

    public String getPk_org() {
        return pk_org;
    }

    public void setPk_org(String pk_org) {
        this.pk_org = pk_org;
    }

    /**
     * 根据临时表中字段信息拼装报表查询字段
     */
    public String getSelFieldsByTmpTableColumns(String...columns){
        if(columns == null)
            return "";
        StringBuilder sb = new StringBuilder();
        for(String column : columns){
            sb.append(",")
                    .append(column);
        }
        return sb.toString().substring(1);
    }

    /**
     * 处理params插入的？
     * @return
     */
    public String getInsertValueParams(int length) {
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < length;i ++){
            sb.append(",?");
        }
        return sb.substring(1);
    }
}